/*********************************************************************
 * Filename:      goblin_sqs_queue.h
 *                
 * It belongs to goblin-os.
 *                
 * Version:       
 * Author:        Ins <InsFous@gmail.com>
 * Created at:    Fri Dec 10 17:38:30 2010
 * Description:   
 *                
 ********************************************************************/
#ifndef _GOBLIN_SQS_QUEUE_H_
#define _GOBLIN_SQS_QUEUE_H_

#include "thrift/Queue.h"
#include "goblin/structure/list.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <time.h>

#include <string>
#include <queue>

using goblin::sqs::thrift::Message;
using goblin::sqs::thrift::MessageID;
using goblin::sqs::thrift::QueueName;

struct QueueNode {
  struct list_head list;
  Message *msg;
};

namespace goblin {
  namespace sqs {
    const int64_t kQueueDefaultCapacity = 10000000;
    struct DBMetaData {
      int64_t db_num;
      int64_t last_db_index;
      int64_t max_msg_id;
    };
    struct DBHeader {
      int64_t begin_write_offset;
      int64_t last_msg_id;
    };
    struct DBMessage {
      int64_t msg_id;
      int64_t msg_insert_time;
      int32_t msg_type;
      int64_t msg_content_len;
      char    msg_content[0];
    };
    class Queue {
    public:
      Queue(const QueueName &queue_name, const std::string &db_dir);
      ~Queue();
      bool PushMessage(const std::string &msg_content, const int32_t msg_type);
      bool GetMessage(Message &msg);
      bool PopMessage();
      inline int64_t UnreadMsgCount(){return unread_msg_count_;}
      inline int64_t TotalMsgCount(){return current_max_msg_id_;}
      bool SetCapacity(const int64_t capacity);
      inline int64_t Capacity(){return capacity_;}
      inline void SetFilter(const int32_t msg_type){filter_ = msg_type;}
      inline void RestoreDefaultFilter(){filter_ = -1;}
      void SyncToDisk();
      void Save();
    private:
      inline MessageID AllocMessageID(){
	return ++current_max_msg_id_;
      }
      void Init();
      void WriteMetaData();
      void ReadMetaData();
      void WriteUnSyncMsgs();
      void WriteUnreadMsgs();
      void ReadinUnreadMsgs();
    private:
      struct QueueNode *unread_msgs_;
      uint64_t unread_msg_count_;
      struct QueueNode *unsync_to_disk_msgs_;
      uint64_t unsync_to_disk_msg_count_;
      MessageID current_max_msg_id_;
      int64_t   capacity_;
      int32_t   filter_;
      QueueName queue_name_;
      std::string db_dir_;
      int64_t unsync_to_disk_msgs_max_msg_id_;
      int64_t db_num_;
      int64_t last_db_index_;
      pthread_mutex_t mutex_lock_;
    };
  }
}



#endif  // _GOBLIN_SQS_QUEUE_H_
